Imports DotNetNuke.UI.WebControls
Imports DotNetNuke.UI.WebControls.DNNTabStrip

'-------------------------------------------------------------------------------------------
'Note:  Throughout these examples you will see comments about viewstate being disabled for
'		dropdowns, therefore we are using the request object.  For more information on this
'		subject see the following blog entry.
'		http://dotnetnuke.com/DotNetNukeProjects/CoreWebControls/tabid/873/EntryID/1042/Default.aspx
'-------------------------------------------------------------------------------------------

Public Class TabStripRendering
    Inherits System.Web.UI.Page

    Public Enum TabRenderMode
        All
        Postback
        Callback
        PartialRendering
    End Enum

#Region "Member Variables"
    Private m_objInfo As PageInfo
    Private m_aryLocations() As String = {"Top", "Bottom", "Left", "Right"} 'used to show declarative databinding to dropdown 
#End Region

#Region "Properties"

    'retrieves tabrendermode from querystring
    Public ReadOnly Property RenderMode() As TabRenderMode
        Get
            If Len(Request.QueryString("mode")) > 0 Then
                Return CInt(Request.QueryString("mode"))
            End If
            Return TabRenderMode.All
        End Get
    End Property

    'in order to simulate work we will use the sleep command throughout this example
    'encapsulating it in a property that checks the querystring allows it to be easily overridden
    Public ReadOnly Property DelayLength() As Integer
        Get
            If Len(Request.QueryString("delay")) > 0 Then
                Return CInt(Request.QueryString("delay"))
            End If
            Return 1000       'default to half a second
        End Get
    End Property

    'property to obtain the Id of the info object we are updating.  -1 means new
    Public ReadOnly Property DataId() As Integer
        Get
            If Len(Request.QueryString("id")) > 0 Then
                Return CInt(Request.QueryString("id"))
            End If
            Return -1
        End Get
    End Property

    'if id is passed on the querystring (DataId) then assume we are editing an existing record and pull the data
    'from the dataservice layer, otherwise we are assuming a new record, where the values are defaulted from 
    'the Info's constructor
    Public ReadOnly Property PageData() As PageInfo
        Get
            If m_objInfo Is Nothing Then
                If DataId > -1 Then
                    m_objInfo = DataServices.GetTabData(DataId)
                Else
                    m_objInfo = New PageInfo
                End If
            End If
            Return m_objInfo
        End Get
    End Property

    'used to show declarative databinding to dropdown 
    Public ReadOnly Property Locations() As String()
        Get
            Return m_aryLocations
        End Get
    End Property

#End Region

#Region "Event Handlers"
    'Technically this is only needed if we are using the callback rendering mode
    Protected Overrides Sub OnInit(ByVal e As System.EventArgs)
        MyBase.OnInit(e)
        'this is necessary to enable client callbacks.  If you coding inside DotNetNuke, this is NOT needed
        DotNetNuke.UI.Utilities.ClientAPI.HandleClientAPICallbackEvent(Me)

        If Me.RenderMode = TabRenderMode.PartialRendering Then
            ScriptManager.GetCurrent(Me.Page).EnablePartialRendering = True
        End If
    End Sub

    Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        SetUpRenderMode()
        If Not Me.IsPostBack Then
            'since we are populating all tabs in initial load both of these functions could be changed to
            'InitializeControls and BindControls where both the tab controls and the non-tab controls 
            'perform their respective logic.  However, I think it will be more helpful in comparing 
            'if all pages utilize the same function names
            InitializeNonTabControls()
            BindNonTabControls()
        Else
            MethodCalled(">>> POSTBACK - Size: " & Me.Request.TotalBytes.ToString, False)

        End If

    End Sub

    Protected Sub tabGeneral_SetupDefaults() Handles tabGeneral.SetupDefaults
        MethodCalled("SetupDefaults: tabGeneral", False)
        If tabGeneral.IsPostBack = False Then
            MethodCalled("BindTab: tabGeneral", True)
            'bind tab
            Me.txtName.Text = PageData.name
            Me.txtDesc.Text = PageData.description
        End If
    End Sub

    Protected Sub tabAdvanced_SetupDefaults() Handles tabAdvanced.SetupDefaults
        MethodCalled("SetupDefaults: tabAdvanced", True)

        'always need to populate items since viewstate disabled
        RefreshColors()
        Me.ddlLocation.DataBind()

        If tabAdvanced.IsPostBack Then  'if tab was rendered, we may need to re-select the listitems that were posted
            'since we are not using the viewstate hack we need to reselect the listitem
            FormUtil.SelectItem(Me.ddlColor, Request.Form(Me.ddlColor.UniqueID))
            FormUtil.SelectItem(Me.ddlLocation, Request.Form(Me.ddlLocation.UniqueID))
        Else
            MethodCalled("BindTab: tabAdvanced", True)
            'bind tab
            Me.txtFont.Text = PageData.font
            FormUtil.SelectItem(Me.ddlColor, PageData.color)
            FormUtil.SelectItem(Me.ddlLocation, PageData.location)
        End If
    End Sub

    Protected Sub btnNew_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnNew.Click
        NewForm()
    End Sub

    Protected Sub btnSave_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnSave.Click
        SaveForm()
    End Sub

#End Region

#Region "Private Methods"

    'setting navigation header info
    Private Sub SetUpRenderMode()
        Select Case RenderMode
            Case TabRenderMode.All
                Me.MyDNNTabStrip.TabRenderMode = eTabRenderMode.All
                Me.lnkAll.Font.Bold = True
                SetRatings(1, 1, 4, 4, 4)
            Case TabRenderMode.Postback
                Me.MyDNNTabStrip.TabRenderMode = eTabRenderMode.PostBack
                Me.lnkPostback.Font.Bold = True
                SetRatings(4, 3, 1, 1, 1)
            Case TabRenderMode.Callback
                Me.MyDNNTabStrip.TabRenderMode = eTabRenderMode.CallBack
                Me.lnkCallback.Font.Bold = True
                SetRatings(4, 4, 3, 3, 3)
            Case TabRenderMode.PartialRendering
                Me.MyDNNTabStrip.TabRenderMode = eTabRenderMode.PostBack
                Me.lnkPartialRendering.Font.Bold = True
                SetRatings(4, 2, 1, 2, 2)
                'Dim oSM As ScriptManager = ScriptManager.GetCurrent(Me.Page)
                Dim objPanel As UpdatePanel = New UpdatePanel
                objPanel.ID = "MyUpdatePanel"
                'objPanel.ContentTemplate = New TemplateBuilder
                objPanel.EnableViewState = False

                'if the updatepanel results would run the script we send down this would not be necessary
                'Me.Page.ClientScript.RegisterStartupScript(Me.GetType, "hookupAtlasPartialRenderingEvent", "Sys.Application.load.add( hookupAtlasPartialRenderingEvent ); ", True)
                Me.Page.ClientScript.RegisterStartupScript(Me.GetType, "hookupAtlasPartialRenderingEvent", "Sys.Application.add_load( initializeAtlasEvents ); ", True)

                'embed tabstrip within updatepanel
                Dim objParent As Control = Me.MyDNNTabStrip.Parent
                For i As Integer = 0 To objParent.Controls.Count - 1
                    If objParent.Controls(i).ID = MyDNNTabStrip.ID Then
                        objParent.Controls.Remove(MyDNNTabStrip)
                        objPanel.ContentTemplateContainer.Controls.Add(MyDNNTabStrip)
                        objParent.Controls.AddAt(i, objPanel)
                        Exit For
                    End If
                Next
        End Select
    End Sub

    Private Sub SetRatings(ByVal InitialProcessing As Integer, ByVal InitialPayload As Integer, ByVal TabRequest As Integer, ByVal TabProcessing As Integer, ByVal TabPayload As Integer)
        SetImage(Me.imgInitialRequestProcessing, InitialProcessing)
        SetImage(Me.imgInitalRequestPayload, InitialPayload)
        SetImage(Me.imgTabRequest, TabRequest)
        SetImage(Me.imgTabRequestProcessing, TabProcessing)
        SetImage(Me.imgTabPayload, TabPayload)
    End Sub
    Private Sub SetImage(ByVal Img As Image, ByVal Stars As Integer)
        Img.ImageUrl = String.Format("../images/{0}stars.gif", Stars)
        Img.Attributes.Add("onmouseover", String.Format("showRatingDesc(this, {0})", CInt(Me.RenderMode)))
    End Sub


    'populate any controls with predefined data, i.e. dropdown lists
    Private Sub InitializeNonTabControls()
        MethodCalled("InitializeNonTabControls", False)
        If Me.DataId = -1 Then      'if this is a new record specify that in the header
            Me.lblTitle.Text = "New Record"
        Else
            Me.lblTitle.Text = String.Format("Edit Record ID: {0}", Me.DataId)
        End If
    End Sub

    'retrive data from database and bind it to non-tab controls on the page
    Private Sub BindNonTabControls()
        MethodCalled("BindPage", False)
        Me.txtPageName.Text = PageData.pagename
    End Sub

    'demonstrate where in the page lifecycle to programmatically populate a dropdown
    Private Sub RefreshColors()
        MethodCalled("RefreshColors", False)
        Me.ddlColor.Items.Add(New ListItem("Blue", "blue"))
        Me.ddlColor.Items.Add(New ListItem("Green", "green"))
        Me.ddlColor.Items.Add(New ListItem("Red", "red"))
    End Sub

    'this method is responsible for populating the info entity object with the
    'posted values.  Note:  If a tab was not rendered on the client, the pre-existing
    'values will be kept
    Private Sub SaveForm()
        MethodCalled("SaveForm", False)

        Debug("==> Saving Non-Tab Controls...")
        Me.PageData.pagename = Me.txtPageName.Text

        If Me.MyDNNTabStrip.Tabs(0).IsPostBack Then
            Debug("==> Saving tabGeneral...")
            PageData.name = Me.txtName.Text
            PageData.description = Me.txtDesc.Text
        Else
            Debug("==> tabGeneral NOT Rendered - Using Defaults...")
        End If
        If Me.MyDNNTabStrip.Tabs(1).IsPostBack Then
            Debug("==> Saving tabAdvanced...")
            PageData.font = Me.txtFont.Text
            PageData.color = Request.Form(Me.ddlColor.UniqueID)      'viewstate disabled using request
            PageData.location = Request.Form(Me.ddlLocation.UniqueID) 'viewstate disabled using request
        Else
            Debug("==> tabAdvanced NOT Rendered - Using Defaults...")
        End If
        PersistData()

    End Sub

    'this method simulates the saving of the info to the database
    'instead of calling the dataservices we simply output the results
    'to the client
    Private Sub PersistData()
        MethodCalled("PersistData", True)
        Debug("___________________________________________________")
        Debug("--- This is the data to be sent to the database ---")
        Debug("name=" & PageData.name)
        Debug("description=" & PageData.description)
        Debug("font=" & PageData.font)
        Debug("location=" & PageData.location)
        Debug("color=" & PageData.color)
        Debug("___________________________________________________")
    End Sub

    Private Sub NewForm()
        'yes, I know it is more efficient to do on client.  Thought this would be clearer to those reviewing the code
        Response.Redirect(Me.Request.Path & "?id=-1")
    End Sub
#End Region

#Region "Debugging Routines"
    Private Sub MethodCalled(ByVal Method As String, ByVal DoDelay As Boolean)
        If DoDelay Then
            Method &= " (Delay " & (Me.DelayLength / 1000) & "secs)"
            Delay()
        End If
        Me.txtMethods.Value &= (Me.txtMethods.Value.Split(vbCrLf).Length) & ". " & Method & vbCrLf
        System.Diagnostics.Debug.WriteLine("----------------------")
        System.Diagnostics.Debug.WriteLine(Me.txtMethods.Value)
        System.Diagnostics.Debug.WriteLine("----------------------")

    End Sub

    Private Sub Debug(ByVal Message As String)
        Me.txtDebug.Value &= Message & vbCrLf
    End Sub

    'simulates work
    Private Sub Delay()
        System.Threading.Thread.Sleep(Me.DelayLength)
    End Sub

#Region "This code is only necessary to write out the page size.  Not worth reviewing, as it is a minor hack"
    Protected Overrides Sub Render(ByVal writer As System.Web.UI.HtmlTextWriter)
        Me.MethodCalled(">>> Render Size: [RENDERSIZEHERE]", False)     'mini hack
        Dim objSW As System.IO.StringWriter = New System.IO.StringWriter
        Dim objMyWriter As New HtmlTextWriter(objSW)
        MyBase.Render(objMyWriter)
        Dim strHTML As String = objSW.ToString()
        strHTML = strHTML.Replace("[RENDERSIZEHERE]", strHTML.Length.ToString)
        writer.Write(strHTML)
    End Sub
#End Region

#End Region

End Class
